package llama.view.panels;

import java.awt.BorderLayout;
import java.awt.Color;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.SwingConstants;

import llama.core.IMessage;
import llama.core.IUser;
import llama.ctrl.ControllerFactory;
import llama.ctrl.ConversationCtrl;
import llama.ctrl.ConversationCtrl.ConversationOption;

/**
 * 
 */
public class ChatTabPanel extends JPanel {
	private JTabbedPane tabbedPane;
	private int activeConversationIndex;
	
	/**
	 * Create the panel.
	 */
	public ChatTabPanel() {
		setLayout(new BorderLayout(0, 0));
		
		tabbedPane = new JTabbedPane(SwingConstants.TOP);
		tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
		add(tabbedPane, BorderLayout.CENTER);

	}
	
	/**
	 * Clear the JTabbedPane from components.
	 */
	public void clearTabs() {
		tabbedPane.removeAll();
	}


	public void appendMessage(final IMessage msg) {
		if(msg.isMessageByMe()) {
			processMessage(msg.getToUser(), msg, Color.blue);
		} else {
			processMessage(msg.getFromUser(), msg, Color.red);
		}
	}
	
	private void processMessage(final IUser fromUser, final IMessage message, final Color color) {
		int conversationIndex = getConversationIndex(fromUser);
		System.out.println(fromUser);
		System.out.println(conversationIndex);
		if(conversationIndex == -1) {
			conversationIndex = createTab(fromUser);
			sendCurrentConversationInformation();
		}
		
		Date date = message.getDate();
		SimpleDateFormat df = new SimpleDateFormat("[hh:mm:ss]");
		
		ChatTextPanel chatTextPanel = (ChatTextPanel) tabbedPane.getComponentAt(conversationIndex);
		chatTextPanel.appendText(df.format(date)+" ", message.getFromUser().getEmail(), color, message.getMessage());
		
		updateHighlightConversation(fromUser);
	}
	
	/**
	 * Gets the amount of tabs.
	 * @return the amount of tabs.
	 */
	public int getTabCount() {
		return tabbedPane.getTabCount();
	}
	
	/**
	 * Close the tab associated with the provided email-address.
	 * @param email The user associated with the tab that should be closed. 
	 */
	public void closeTab(final IUser email) {
		int conversationIndex = getConversationIndex(email);
		
		if(conversationIndex > -1 && conversationIndex < tabbedPane.getTabCount()) {
			tabbedPane.removeTabAt(conversationIndex);
			
			if(activeConversationIndex >= conversationIndex) {
				activeConversationIndex--;
			}
			
			if(activeConversationIndex < tabbedPane.getTabCount()
					&& activeConversationIndex > -1) {
				tabbedPane.setSelectedIndex(activeConversationIndex);
			} else if (activeConversationIndex-1 > tabbedPane.getTabCount()) {
				tabbedPane.setSelectedIndex(activeConversationIndex-1);
			} else if (activeConversationIndex+1 < -1) {
				tabbedPane.setSelectedIndex(activeConversationIndex+1);
			} else {
				//This should never happen since the last tab is supposed to close the window
				//Since it's not handled here atm, it is handled elsewhere.
			}
			
			sendCurrentConversationInformation();
		}
		
	}
	
	/**
	 * Activates a conversation by creating a new tab and selecting it. 
	 * If a tab associated with the provided email-address already exist this tab will be selected instead.
	 * @param user - The user associated with conversation that should be activated. 
	 */
	public void activateConversation(final IUser user) {		
		boolean select = selectTab(user);
		if(!select) {
			createTab(user);
			selectTab(user);
		}
		
		activeConversationIndex = getConversationIndex(user);
	}
	
	/**
	 * Creates a conversation/tab and associates it with the provided email-address.
	 * @param user - the user the conversation should be associated with.
	 * @return the index of the newly created conversation/tab.
	 */
	private int createTab(final IUser user) {
		tabbedPane.addTab(user.getEmail(), null, new ChatTextPanel(user), "Conversation with "+user);
		tabbedPane.setTabComponentAt(getConversationIndex(user), new ClosableTabPanel(user));
		return getConversationIndex(user);
	}
	
	/**
	 * Selects a conversation bringing it to the front.
	 * @param user - the user associated with the tab that should be selected.
	 * @return true if a tab was selected.
	 */
	private boolean selectTab(final IUser user) {
		int conversationIndex = getConversationIndex(user);
		if(conversationIndex != -1) {
			tabbedPane.setSelectedIndex(conversationIndex);
			deHighlightSelectedConversation();
			return true;
		}
		
		return false;
	}	
	
	/**
	 * This method highlights the conversation associated with the provided email.
	 * A conversation should be highlighted when it's not in focus and a message was appended.
	 * @param user - the user associated with the tab that should be highlighted.
	 * @see deHighlightSelectedConversation().
	 */
	private void updateHighlightConversation(final IUser user) {
		int conversationIndex = getConversationIndex(user);
		if(conversationIndex != -1 
				&& conversationIndex == tabbedPane.getSelectedIndex()) {
			ClosableTabPanel ctp = (ClosableTabPanel) tabbedPane.getTabComponentAt(conversationIndex);
			ctp.deHighlight();
		} else if(conversationIndex != -1) {
			ClosableTabPanel ctp = (ClosableTabPanel) tabbedPane.getTabComponentAt(conversationIndex);
			ctp.highlight();
		}
	}
	
	/**
	 * De-highlights the selected conversation.
	 * @see updateHighlightConversation(String).
	 */
	private void deHighlightSelectedConversation() {
		if(tabbedPane.getSelectedIndex() != -1) {
			Object obj = tabbedPane.getTabComponentAt(tabbedPane.getSelectedIndex());
			((ClosableTabPanel) obj).deHighlight();
		}
	}

	/**
	 * Returns the index of the tab associated with the provided email-address. If the tab
	 * wasn't found the method returns -1.
	 * @param user the user associated with the sought tab.
	 * @return index of tab or -1 if the tab wasn't found.
	 */
	private int getConversationIndex(final IUser user) {
		for (int i = 0; i < tabbedPane.getTabCount(); i++) {
			ChatTextPanel chatTextPanel = (ChatTextPanel) tabbedPane.getComponentAt(i);
			if(chatTextPanel != null && chatTextPanel.getUser().equals(user)) {
				return i;
			}
		}
		
		return -1;
	}
	
	/**
	 * This method should be called when tab selection changes, it sends an event through ConversationCtrl allowing the Conversation-GUI to update.
	 */
	private void sendCurrentConversationInformation() {
		if(tabbedPane.getSelectedComponent() != null 
				&& tabbedPane.getSelectedComponent() instanceof ChatTextPanel) {
			
			ChatTextPanel chatTextPanel = (ChatTextPanel) tabbedPane.getSelectedComponent();
			ConversationCtrl conversationCtrl = (ConversationCtrl) ControllerFactory.getController(ConversationCtrl.class);
			conversationCtrl.setSelectedContact(ConversationOption.SELECT, chatTextPanel.getUser());
			conversationCtrl.execute();
		}
	}
}
